/***************************************************************************
 *   oboe.controllers.jml.helpers.window.JMLWindow                         *
 *   Copyright (C) 2011 by Felipe Manga                                    *
 *   lufeboma@gmail.com                                                    *
 *                                                                         *
 *   Permission is hereby granted, free of charge, to any person obtaining *
 *   a copy of this software and associated documentation files (the       *
 *   "Software"), to deal in the Software without restriction, including   *
 *   without limitation the rights to use, copy, modify, merge, publish,   *
 *   distribute, sublicense, and/or sell copies of the Software, and to    *
 *   permit persons to whom the Software is furnished to do so, subject to *
 *   the following conditions:                                             *
 *                                                                         *
 *   The above copyright notice and this permission notice shall be        *
 *   included in all copies or substantial portions of the Software.       *
 *                                                                         *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       *
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    *
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR     *
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
 *   OTHER DEALINGS IN THE SOFTWARE.                                       *
 ***************************************************************************/

package oboe.controllers.jml.helpers.window
{
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.text.TextField;
	
	import oboe.controllers.jml.JMLController;
	import oboe.controllers.jml.helpers.JMLNode;

	public class JMLWindow extends JMLNode
	{
		public function JMLWindow( key:String, val:Object, parent:JMLController )
		{
			super( key, val, parent );
		}
		
		protected override function createDisplayObject(type:String):DisplayObject
		{
			return new WindowView();
		}
	}
}

import flash.display.DisplayObject;
import flash.display.GradientType;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.DropShadowFilter;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;

import oboe.controllers.jml.events.JMLEvent;
import oboe.core.Controller;
import oboe.core.Oboe;
import oboe.math.Number2D;

class WindowView extends Sprite
{
	private var dragData:DragData;

	public var titleBarHeight:int = 20;
	public var titleBarColor1:int = 0xE0E0E0;
	public var titleBarColor2:int = 0xA0A0A0;
	public var windowFillColor:int = 0x7F7F7F;
	public var windowBorderColor:int = 0xAFAFAF;
	public var titleBarTextColor:int = 0x0F0F0F;
	
	private var minSize:Number2D;
	
	public function WindowView()
	{
		super();
		Object(this).addCallback( JMLEvent.JMLCOMPLETE, onComplete).once = true;
	
		this.minSize = new Number2D(0,0);
		
		this.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
		this.dragData = new DragData();
		
		// Flash bugfix for sprite to report correct width/height
		this.graphics.beginFill(0, 1);
		this.graphics.drawRect(0,0,1000,1000);
		this.graphics.endFill();
	}
	
	public function requireMinSize( w:int, h:int ):void
	{
		minSize.x = Math.max( minSize.x, w );
		minSize.y = Math.max( minSize.y, h );
	}
	
	private function onMouseDown( e:MouseEvent ):void
	{
		if( e.target == this && e.localY < this.titleBarHeight ) 
		{
			this.dragData.startDrag( this, e );
		}
	}
	
	private function onAddToStage():void
	{
		this.x = this.stage.stageWidth/2 - this.width/2;
		this.y = this.stage.stageHeight/2 - this.height/2;
	}
	
	private function onComplete( ):void
	{
		if( !this.x && !this.y )
		{
			Object(this).addCallback( Event.ADDED_TO_STAGE, onAddToStage );
		}
		
		this.requireMinSize( 100, this.titleBarHeight + this.resizeButtonSize );

		this.redraw();

		this.filters = [
			new DropShadowFilter(5, 45, 0, 0.5, 6, 6)
		];
	}
	
	public function redraw():void	
	{
		var width:Number = this.width;
		var height:Number = this.height;
		this.scaleX = this.scaleY = 1;
		this.graphics.clear();
		
		this.drawWindow( width, height );
	}
	
	include "_closebutton.as3";
	include "_resizebutton.as3";
	
	private function drawWindow( width:Number, height:Number ):void
	{
		width = Math.max( width, this.minSize.x );
		height = Math.max( height, this.minSize.y );
		
		this.scrollRect = new Rectangle(0, 0, width, height);
		
		this.graphics.clear();
		
		this.graphics.lineStyle(2, this.windowBorderColor, 1);
		this.graphics.beginFill( this.windowFillColor, 1);
		this.graphics.drawRect(0, 0, width, height);
		this.graphics.endFill();
		
		// this.graphics.beginFill( this.titleBarColor, 1);
		var box:Matrix = new Matrix();
		box.createGradientBox( width, titleBarHeight, Math.PI/2 );
		this.graphics.beginGradientFill( GradientType.LINEAR, [this.titleBarColor1, this.titleBarColor2], [1, 1], [0, 255], box );
		this.graphics.drawRect(0, 0, width, titleBarHeight);
		this.graphics.endFill();
		
		adjustControl(
			width, height,
			this.showCloseButton, 
			this.closeButtonSprite, 
			this.addCloseButton,
			this.adjustCloseButton
		);
		adjustControl( 
			width, height,
			this.showResizeButton, 
			this.resizeButtonSprite, 
			this.addResizeButton,
			this.adjustResizeButton
		);
	}
	
	private function adjustControl( width:Number, height:Number, flag:Boolean, asset:DisplayObject, factory:Function, adjust:Function ):void
	{
		if( flag )
		{
			if( !asset ) asset = factory();
			adjust( width, height );
			
			if( asset.parent != this )
			{
				this.addChild( asset );
			}
		}
		else
		{
			if( asset && asset.parent == this )
			{
				this.removeChild( asset );
			}
		}
	}
	
	public function set title(t:String):void
	{
		if( !titleAsset )
		{
			titleAsset = new TextField();
			titleAsset.textColor = titleBarTextColor;
			titleAsset.autoSize = TextFieldAutoSize.LEFT;
			titleAsset.mouseEnabled = false;
			this.addChild( titleAsset );
		}
		
		titleAsset.text = t;
	}
	
	private var titleAsset:TextField;
}

class DragData
{
	public var isDragging:Boolean;
	public var dragOffset:Number2D;
	private var target:DisplayObject;
	private var callback:Function;
	
	public function DragData()
	{
		this.isDragging = false;
		this.dragOffset = new Number2D(0,0);
	}
	
	public function startDrag( target:DisplayObject, e:MouseEvent, callback:Function=null ):void
	{
		this.target = target as DisplayObject;
		this.callback = callback;
		if( !this.isDragging )
		{
			Oboe.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
		}
		
		this.dragOffset.set( e.stageX, e.stageY );
		this.isDragging = true;
	}
	
	private function onMouseMove( e:MouseEvent ):void
	{
		if( !this.isDragging || !e.buttonDown )
		{
			Oboe.stage.removeEventListener( MouseEvent.MOUSE_MOVE, onMouseMove );
			this.isDragging = false;
			Oboe.stage.mouseChildren = true;
			return;
		}
		
		Oboe.stage.mouseChildren = false;
		
		var deltaX:Number = e.stageX - this.dragOffset.x;
		var deltaY:Number = e.stageY - this.dragOffset.y;
		this.target.x += deltaX;
		this.target.y += deltaY;
		this.dragOffset.x = e.stageX;
		this.dragOffset.y = e.stageY;
		if( this.callback != null ) this.callback( this.target.x, this.target.y );
	}
}